home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 19 / CU Amiga Magazine's Super CD-ROM 19 (1998)(EMAP Images)(GB)[!][issue 1998-02].iso / CUCD / Programming / LEDA / prog / graphics / delaunay.c < prev    next >
C/C++ Source or Header  |  1994-08-05  |  6KB  |  362 lines

  1. #include <LEDA/impl/delaunay_tree.h>
  2. #include <LEDA/plane.h>
  3. #include <LEDA/window.h>
  4.  
  5.  
  6. window* Wp;
  7.  
  8. const double R = 1000;  // "length of inifinite rays"
  9.  
  10. int ymax;
  11.  
  12. int segment_to_points(segment s, list<point>& out, double dist)
  13.   int n = int(s.length()/dist) + 2;
  14.  
  15.   double dx = (s.xcoord2() - s.xcoord1())/n;
  16.   double dy = (s.ycoord2() - s.ycoord1())/n;
  17.   double x  = s.xcoord1();
  18.   double y  = s.ycoord1();
  19.  
  20.   out.append(s.start());
  21.  
  22.   for(int i = 0; i<n; i++)
  23.   { x += dx + double(random(-100,100))/1000000;
  24.     y += dy + double(random(-100,100))/1000000;
  25.     out.append(point(x,y));
  26.    }
  27.  
  28.   return n;
  29.  
  30. }
  31.  
  32. int circle_to_points(circle C, list<point>& out, double dist)
  33.   point c = C.center();
  34.   double r = C.radius();
  35.   int n = int(6.283 * r/dist);
  36.  
  37.   double alpha = 0;
  38.   double d = 6.283/n;
  39.  
  40.   for(int i = 0; i<n; i++)
  41.   { out.append(c.translate(alpha,r+double(random(-100,100))/1000000));
  42.     alpha += d;
  43.    }
  44.  
  45.   out.permute();
  46.  
  47.  return n;
  48.  
  49. }
  50.  
  51.  
  52.  
  53.  
  54. void draw_vor_site(double x, double y)
  55. { Wp->draw_point(x,y,blue); }
  56.  
  57. void draw_vor_seg(double x1, double y1, double x2, double y2,double,double)
  58. { Wp->draw_segment(x1,y1,x2,y2,red); }
  59.  
  60.  
  61. void draw_triang_seg(double x1, double y1, double x2, double y2)
  62. { Wp->draw_segment(x1,y1,x2,y2,green); 
  63.  }
  64.  
  65. void infi_pt(double x1, double y1, double x2, double y2, double *x, double* y)
  66. /* retourne le point a l'infini dans la direction x2 y2 depuis x1 y1*/
  67. {
  68.   vector v(x2,y2);
  69.  
  70.   v = v.norm();
  71.  
  72.   *x = x1 + R * v[0];
  73.   *y = y1 + R * v[1];
  74.   
  75. }
  76.  
  77.  
  78.  
  79. DELAUNAY_TREE<int> DT;
  80.  
  81. int display = 0;
  82. DT_item near_it = nil;
  83. bool vor = false;
  84. bool triang = false;
  85. list<segment> CH;
  86.  
  87.  
  88. void insert_point(point p)
  89. { Wp->draw_point(p,blue);
  90.   DT.insert(p,0);
  91.  }
  92.  
  93. void insert_segment(segment s)
  94. { list<point> pl;
  95.   segment_to_points(s,pl,10/Wp->scale());
  96.   point p;
  97.   forall(p,pl) insert_point(p);
  98. }
  99.  
  100. void insert_circle(circle c)
  101. { list<point> pl;
  102.   circle_to_points(c,pl,10/Wp->scale());
  103.   point p;
  104.   forall(p,pl) insert_point(p);
  105. }
  106.             
  107.  
  108.  
  109. void draw()
  110. { segment s;
  111.   switch(display) {
  112.  
  113.   case 0: DT.trace_voronoi_edges(draw_vor_seg,infi_pt);
  114.           break;
  115.  
  116.   case 1: DT.trace_triang_edges(draw_triang_seg);
  117.           break;
  118.  
  119.   case 2: { list<DT_item> L;
  120.             DT.convex_hull(L);
  121.             list_item it;
  122.             Wp->set_line_width(2);
  123.             forall_items(it,L) 
  124.             { point p = DT.key(L[it]);
  125.               point q = DT.key(L[L.cyclic_succ(it)]);
  126.               Wp->draw_segment(p,q,violet);
  127.              }
  128.             Wp->set_line_width(1);
  129.             break;
  130.            }
  131.   }
  132. }
  133.  
  134.  
  135. void redraw()
  136. { DT.trace_voronoi_sites(draw_vor_site);
  137.   draw();
  138. }
  139.  
  140.  
  141. void interactive(window& W)
  142. {
  143.   W.set_redraw(redraw);
  144.   W.set_mode(xor_mode);
  145.   W.set_node_width(4);
  146.  
  147.   panel P("DYNAMIC VORONOI DIAGRAMS");
  148.  
  149.   P.text_item("            based on Delaunay Trees           ");
  150.   P.text_item("             by Olivier Devillers             ");
  151.   P.text_item("                                              ");
  152.  
  153.   int but = -1;
  154.  
  155.   int N = 500;
  156.   int grid_width = 0;
  157.  
  158.   P.choice_item("show",display,"voronoi","triang","c-hull");
  159.   P.int_item("grid", grid_width,0,40);
  160.   P.int_item("rand sites ",N);
  161.  
  162.   P.button("random");
  163.   P.button("point");
  164.   P.button("segment");
  165.   P.button("circle");
  166.   P.button("delete");
  167.   P.button("neighbor");
  168.   P.button("clear");
  169.   P.button("quit");
  170.  
  171. for(;;)
  172. {
  173.   draw();  // draw picture
  174.  
  175.   but=P.open(0,0);
  176.  
  177.   if (but == 7) break;
  178.  
  179.   draw();  // delete previous drawing
  180.  
  181.   W.set_grid_mode(grid_width);
  182.  
  183.   switch (but) { 
  184.  
  185.     case 0: { for(int i=0; i<N; i++)
  186.                 insert_point(point(random(10,500),random(10,ymax)));
  187.               break;
  188.              }
  189.  
  190.     case 1: { point p;
  191.               while (W >> p)  insert_point(p);
  192.               break;
  193.              }
  194.  
  195.     case 2: { segment s;
  196.               while (W >> s) insert_segment(s);
  197.               break;
  198.              }
  199.  
  200.     case 3: { circle c;
  201.               while (W >> c) insert_circle(c);
  202.               break;
  203.              }
  204.  
  205.     case 4: { point p;
  206.               while (W >> p)
  207.               { DT_item it = DT.neighbor(p); 
  208.                 if (it) 
  209.                 { W.draw_point(DT.key(it),blue);
  210.                   DT.del_item(it); 
  211.                  }
  212.                }
  213.               break;
  214.              }
  215.  
  216.     case 5: { point p;
  217.               while (W >> p)
  218.               { if (near_it) W.draw_filled_node(DT.key(near_it));
  219.                 near_it = DT.neighbor(p); 
  220.                 if (near_it) W.draw_filled_node(DT.key(near_it));
  221.               }
  222.               if (near_it) W.draw_filled_node(DT.key(near_it));
  223.               near_it = nil;
  224.               break;
  225.              }
  226.  
  227.     case 6: { DT.clear();
  228.               W.clear();
  229.               CH.clear();
  230.               near_it = nil;
  231.              }
  232.     }  // switch
  233.  
  234.  } // for(;;)
  235.  
  236. }
  237.  
  238.  
  239.  
  240. void demo(int N, int sec)
  241. { int i;
  242.  
  243.   while(Wp->get_button() == 0)
  244.   {
  245.     DT.clear();
  246.     Wp->clear();
  247.     Wp->message(string("%d sites",N));
  248.     Wp->flush();
  249.  
  250.     for (i=0; i<N ; i++)
  251.     { point p(random(10,500),random(10,ymax));
  252.       DT.insert(p,i);
  253.       *Wp << p;
  254.      }
  255.  
  256.  
  257.     //DT.trace_voronoi_sites( draw_vor_site);
  258.  
  259.     DT.trace_voronoi_edges( draw_vor_seg,infi_pt);
  260.     Wp->flush();
  261.     wait(sec);
  262.  
  263.     Wp->clear();
  264.  
  265.     DT.trace_triang_edges( draw_triang_seg);
  266.     Wp->flush();
  267.     wait(sec);
  268.   }
  269.  
  270. }
  271.  
  272.  
  273. /*
  274. #include <LEDA/stream.h>
  275. */
  276.  
  277.  
  278. main(int argc, char** argv)
  279. {
  280.  
  281. /*
  282.  
  283. #define SCREEN_WIDTH  1152
  284. #define SCREEN_HEIGHT  900
  285.  
  286.   string_istream arguments(argc-1,argv+1);
  287.  
  288.   int   N=0;
  289.  
  290.   float f1=1; 
  291.   float f2=1;
  292.  
  293.   float w,h,xpos,ypos;
  294.  
  295.   int   position=0;
  296.  
  297.   arguments >> f1;
  298.   arguments >> f2;
  299.  
  300.   if (f1 == 0 && f2 == 0) 
  301.    { f1 = 0.75;
  302.      f2 = 0.95;
  303.     }
  304.   else 
  305.    if (f2 == 0) 
  306.      f2 = f1;
  307.    else
  308.      { arguments >> position;
  309.        arguments >> N;
  310.       }
  311.  
  312.  
  313.   w = SCREEN_WIDTH*f1;
  314.   h = SCREEN_HEIGHT*f2;
  315.  
  316.   switch(position) {
  317.  
  318.   case 0: xpos = SCREEN_WIDTH - w;    // upper right corner
  319.           ypos = 0;
  320.           break; 
  321.  
  322.   case 1: xpos = 0;                   // upper left corner
  323.           ypos = 0;
  324.           break; 
  325.  
  326.   case 2: xpos = 0;
  327.           ypos = SCREEN_HEIGHT - h;   // lower left corner
  328.           break; 
  329.  
  330.   case 3: xpos = SCREEN_WIDTH - w;    // lower right corner
  331.           ypos = SCREEN_HEIGHT - h;
  332.           break; 
  333. }
  334.  
  335.  
  336.   window W(w,h,xpos,ypos);
  337.  
  338. */
  339.  
  340.  
  341.   int N = (argc > 1) ? atoi(argv[1]) : 0;
  342.  
  343.   window W;
  344.  
  345.   W.set_flush(false);
  346.  
  347.   W.init(0,512,0);
  348.  
  349.   Wp = &W;
  350.  
  351.   ymax = int(W.ymax()-10);
  352.  
  353.   if (N==0) 
  354.      interactive(W);
  355.   else
  356.      demo(N,2);
  357.  
  358.  return 0;
  359. }
  360.